home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xpaint-2.1.1
/
iprocess.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
6KB
|
302 lines
/* +-------------------------------------------------------------------+ */
/* | Copyright 1993, David Koblas (koblas@netcom.com) | */
/* | | */
/* | Permission to use, copy, modify, and to distribute this software | */
/* | and its documentation for any purpose is hereby granted without | */
/* | fee, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. There is no | */
/* | representations about the suitability of this software for | */
/* | any purpose. this software is provided "as is" without express | */
/* | or implied warranty. | */
/* | | */
/* +-------------------------------------------------------------------+ */
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include "image.h"
/*
** Some real image processing
*/
#define CLAMP(low, value, high) \
if (value < low) value = low; else if (value > high) value = high
typedef float ConvMatrix[3][3];
static Image *convolve(Image *input, ConvMatrix mat,
unsigned char *basePixel, Boolean absFlag)
{
int x,y,xx,yy, xv,yv;
float sum;
unsigned char *p;
unsigned char *op;
float r, g, b;
int ir, ig, ib;
Image *output;
sum = 0;
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
sum += mat[x][y];
if (sum <= 0)
sum = 0.5;
output = ImageNew(input->width, input->height);
op = output->data;
for (y = 0; y < input->height; y++) {
for (x = 0; x < input->width; x++) {
r = g = b = 0;
sum = 0;
for (yy = 0; yy < 3; yy++) {
for (xx = 0; xx < 3; xx++) {
xv = x + xx - 1;
yv = y + yy - 1;
if (xv < 0 || yv < 0)
continue;
if (xv >= input->width || yv >= input->height)
continue;
p = ImagePixel(input, xv, yv);
r += (float)p[0] * mat[xx][yy];
g += (float)p[1] * mat[xx][yy];
b += (float)p[2] * mat[xx][yy];
sum += mat[xx][yy];
}
}
if (sum <= 0)
sum = 1;
if (absFlag) {
if (r < 0) r = -r;
if (g < 0) g = -g;
if (b < 0) b = -b;
}
ir = r / sum;
if (basePixel) ir += basePixel[0];
CLAMP(0, ir, 255);
ig = g / sum;
if (basePixel) ig += basePixel[1];
CLAMP(0, ig, 255);
ib = b / sum;
if (basePixel) ib += basePixel[2];
CLAMP(0, ib, 255);
*op++ = ir;
*op++ = ig;
*op++ = ib;
}
if (y % 16 == 0)
StateTimeStep();
}
return output;
}
/*
** rescale values from 0..255
*/
static void normalize(Image *image)
{
int i, count;
unsigned char *sp;
unsigned char *ip;
int v, maxval = 0;
if (image->cmapSize != 0) {
sp = image->cmapData;
count = image->cmapSize * 3;
} else {
sp = image->data;
count = image->width * image->height * 3;
}
for (ip = sp, i = 0; i < count; i++, ip++)
if (*ip > maxval)
maxval = *ip;
if (maxval == 0)
return;
for (ip = sp, i = 0; i < count; i++, ip++) {
v = ((int)*ip * 255) / maxval;
CLAMP(0,v,255);
*ip = v;
}
}
/*
** Convert image into a monochrome image
*/
static void monochrome(Image *image)
{
int i, count;
unsigned char *sp;
unsigned char *ip;
int v;
if (image->cmapSize != 0) {
sp = image->cmapData;
count = image->cmapSize;
} else {
sp = image->data;
count = image->width * image->height;
}
for (ip = sp, i = 0; i < count; i++, ip += 3) {
v = (ip[0]*11 + ip[1]*16 + ip[2]*5) >> 5; /* pp=.33R+.5G+.17B */
ip[0] = v;
ip[1] = v;
ip[2] = v;
}
}
Image *ImageSmooth(Image *input)
{
static ConvMatrix mat = {
{ 1, 1, 1 },
{ 1, 1, 1 },
{ 1, 1, 1 }
};
return convolve(input, mat, NULL, False);
}
Image *ImageSharpen(Image *input)
{
static ConvMatrix mat = {
{ -1, -2, -1 },
{ -2, 20, -2 },
{ -1, -2, -1 }
};
return convolve(input, mat, NULL, False);
}
Image *ImageEdge(Image *input)
{
static ConvMatrix mat = {
{ -1, -2, 0 },
{ -2, 0, 2 },
{ 0, 2, 1 }
};
Image *image = convolve(input, mat, NULL, True);
normalize(image);
return image;
}
Image *ImageEmbose(Image *input)
{
static ConvMatrix mat = {
{ -1, -2, 0 },
{ -2, 0, 2 },
{ 0, 2, 1 }
};
static unsigned char base[3] = { 128, 128, 128 };
Image *image = convolve(input, mat, base, False);
monochrome(image);
normalize(image);
return image;
}
Image *ImageInvert(Image *input)
{
Image *output = ImageNewCmap(input->width, input->height, input->cmapSize);
int i;
unsigned char *ip, *op;
int count;
/*
** If the input has a colormap, just invert that.
*/
if (input->cmapSize != 0) {
ip = input->cmapData;
op = output->cmapData;
count = input->cmapSize;
memcpy(output->data, input->data,
sizeof(char) * input->scale * input->width * input->height);
} else {
ip = input->data;
op = output->data;
count = input->width * input->height;
}
for (i = 0; i < count; i++) {
*op++ = 255 - *ip++;
*op++ = 255 - *ip++;
*op++ = 255 - *ip++;
}
return output;
}
#define AREA 7
#define AREA_2 (AREA/2)
Image *ImageOilPaint(Image *input)
{
Image *output = ImageNew(input->width, input->height);
unsigned char *op = output->data;
int x, y, xx, yy, i;
int rVal, gVal, bVal;
int rCnt, gCnt, bCnt;
int rHist[256], gHist[256], bHist[256];
for (y = 0; y < input->height; y++) {
for (x = 0; x < input->width; x++) {
/*
** compute histogram of (on-screen hunk of) n*n
** region centered plane
*/
rCnt = gCnt = bCnt = 0;
rVal = gVal = bVal = 0;
for (i = 0; i < XtNumber(rHist); i++)
rHist[i] = gHist[i] = bHist[i] = 0;
for (yy = y - AREA_2; yy < y + AREA_2; yy++) {
if (yy < 0 || yy >= input->height)
continue;
for (xx = x - AREA_2; xx < x + AREA_2; xx++) {
int c, p;
unsigned char *rgb;
if (xx < 0 || xx >= input->width)
continue;
rgb = ImagePixel(input, xx, yy);
if ((c= ++rHist[(p=rgb[0])/4]) > rCnt) {
rVal = p;
rCnt = c;
}
if ((c= ++gHist[(p=rgb[1])/4]) > gCnt) {
gVal = p;
gCnt = c;
}
if ((c= ++bHist[(p=rgb[2])/4]) > bCnt) {
bVal = p;
bCnt = c;
}
}
}
*op++ = rVal;
*op++ = gVal;
*op++ = bVal;
}
if (y % 16 == 0)
StateTimeStep();
}
return output;
}